<?php
/**
 * cache 缓存类
 * key-value
 * @link http://www.milkphp.com/
 * @author donwa <donwa@milkphp.com>
 * @license New BSD License {@link http://www.milkhphp.com/license/}
 * 
 */
!defined('M_TMP_DIR')&&define('M_TMP_DIR',M_DIR.'tmp/');

/**
 * 
 * 缓存数据存储
 * 
 * //存储缓存
 * milkphp()->cache('test')->a='123123';
 * 
 * //保存300秒
 * milkphp()->cache('test')->set('a','123123',300);
 * 
 * //输出缓存
 * echo milkphp()->cache('test')->a;
 * echo milkphp()->cache('test')->get('a');
 * 
 * //删除缓存
 * milkphp->cache('test')->del('a');
 *
 * //清楚所有test下的缓存
 * milkphp()->cache('test')->clear();
 * 
 *
 */
class lib_cache extends lib_milkphp_library{
	
	/**
	 * 缓存名称
	 * @var string
	 */
	private $_name;
	
	/**
	 * 储存缓存数据
	 * @var array
	 */
	private $_data;
	
	/**
	 * 标记是否修改
	 * @var array
	 */
	private $_write;
	
	
	// cache实现类
	private $_cacheObject;
	
	/*
	 * 单例模式，返回 cache 对象
	 * 
	 * 
	 */
	static function _do($name,$cacheType='file'){
		static $instance=NULL;
		if(isset($instance[$name])){
			return $instance[$name];
		}else{
			return $instance[$name]=new lib_cache($name,$cacheType);
		}
	}
	
	/**
	 * 构造函数 
	 */
	private function __construct($name,$cacheType){
		/**
		 * 判断$name的合法性
		 */
		if(preg_match('/\./',$name)||empty($name)){
			m()->debug('e','缓存名：'.$name.'不合法');
			return FALSE;
		}
		
		$this->_name=$name;
		/**
		 * 判断储存类型
		 */
		$cacheType = 'lib_cache_'.$cacheType;
		$this->_cacheObject = new $cacheType(M_TMP_DIR.'cache/'.trim($name,'/'));
	}
	
	
	//设置数据
	function set($key,$value,$time=-1){
		//序列化加md5,保证$key可以为任意类型
		$key=md5(serialize($key).m("#config")->secCode);
		if(is_null($value))
			return $this->del($key);
			
		switch ($time){
			case -1:
				$time = 9999999999;
				$this->_write[$key]=TRUE;
				break;
			default:
				$time = M_TIME + $time;
				$this->_write[$key]=TRUE;
				break;
		}
		$this->_data[$key]=array('time'=>$time,'value'=>$value);
	}
	
	function __set($key,$value){
		$this->set($key,$value);
	}

	
	//读取数据
	function get($key){
		$key=md5(serialize($key).m("#config")->secCode);
		if(!isset($this->_data[$key]))$this->_data[$key] = $this->load($key);
		return $this->_data[$key]['value'];
	}
	
	function __get($key){
		return $this->get($key);
	}
	
	function load($key){
		$value=NULL;
		$this->_cacheObject->fetch($key,$value);
		
		//删除过期数据
		if(intval($value['time'])<M_TIME){
			$this->del($key);
			return NULL;
		}
		return $value;
	}
	
	//删除数据
	function del($key=""){
		$this->_write[$key]=TRUE;
		$this->_data[$key]=NULL;
	}
	
	//清除数据
	function clear(){
		unset($this->_data);
		unset($this->_write);
		$this->_cacheObject->clear();
	}
	
	//写入文件
	function __destruct(){
		parent::__destruct();
		if(!empty($this->_write)){
			foreach($this->_write as $name => $value){
				if(is_null($this->_data[$name])){
					$this->_cacheObject->delete($name);
				}else{
					$this->_cacheObject->store($name,$this->_data[$name]);
				}
			}
		}
	}
}